package com.springboot.middleware.middleware_rushtopurchase.server.service;

import com.springboot.middleware.middleware_rushtopurchase.model.entity.BookRob;
import com.springboot.middleware.middleware_rushtopurchase.model.entity.BookStock;
import com.springboot.middleware.middleware_rushtopurchase.model.mapper.BookRobMapper;
import com.springboot.middleware.middleware_rushtopurchase.model.mapper.BookStockMapper;
import com.springboot.middleware.middleware_rushtopurchase.server.dto.BookRobDto;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class BookRobServiceImpl implements BookRobService{
    private static final Logger log = LoggerFactory.getLogger(BookRobServiceImpl.class);

    private static final String pathPrefix = "/middleware/zkLock/";

    @Autowired
    private BookRobMapper bookRobMapper;
    @Autowired
    private BookStockMapper bookStockMapper;
    @Autowired
    private CuratorFramework client;

    /**
     * 处理书籍抢购逻辑 - 不加锁
     *
     * @param dto (用户id, 书籍编号)
     * @throws Exception 书籍库存不足
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void robWithNoLock(BookRobDto dto) throws Exception {
        int count = bookRobMapper.countByUserIdBookNo(dto.getUserId(), dto.getBookNo());
        BookStock bookStock = bookStockMapper.selectByBookNo(dto.getBookNo());
        if (bookStock != null && bookStock.getStock() > 0 && count <= 0) {
            log.info("---处理书籍抢购逻辑 不加分布式锁 ---, 当前信息:{}", dto);
            //当前用户抢到书籍, 库存-1
            int res = bookStockMapper.updateStock(dto.getBookNo());
            if (res > 0) {
                BookRob entity = new BookRob();
                BeanUtils.copyProperties(dto, entity);
                entity.setRobTime(new Date());
                bookRobMapper.insertSelective(entity);
            }
        } else {
            throw new  Exception("书籍库存不足");
        }
    }

    /**
     * 处理书籍抢购逻辑 - 加ZK分布式锁
     *
     * @param dto (用户id, 书籍编号)
     * @throws Exception 书籍库存不足 / 获取ZK锁失败
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void robWithZKLock(BookRobDto dto) throws Exception {
        InterProcessMutex mutex = new InterProcessMutex(client, pathPrefix + dto.getBookNo() + dto.getUserId() + "-lock");
        try {
            if (mutex.acquire(15L, TimeUnit.SECONDS)) {
                int count = bookRobMapper.countByUserIdBookNo(dto.getUserId(), dto.getBookNo());
                BookStock bookStock = bookStockMapper.selectByBookNo(dto.getBookNo());
                if (bookStock != null && bookStock.getStock() > 0 && count <= 0) {
                    log.info("---处理书籍抢购逻辑 加zookeeper分布式锁 ---, 当前信息:{}", dto);
                    //当前用户抢到书籍, 库存-1
                    int res = bookStockMapper.updateStock(dto.getBookNo());
                    if (res > 0) {
                        BookRob entity = new BookRob();
                        BeanUtils.copyProperties(dto, entity);
                        entity.setRobTime(new Date());
                        bookRobMapper.insertSelective(entity);
                    }
                } else {
                    throw new  Exception("书籍库存不足");
                }
            } else {
                throw new RuntimeException("获取分布式锁失败");
            }
        } catch (Exception e) {
            throw e;
        } finally {
            mutex.release();
        }
    }
}
